package com.scribbles.common.util;

import java.io.IOException;
import java.security.Principal;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.slf4j.MDC;


/**
 * A Filter that creates generates MDC values for logging.
 * 
 * @author adobson
 */
public class MDCValuesFilter implements Filter
{
    public void init( FilterConfig arg0 ) throws ServletException
    {
    }

    public void destroy()
    {
    }



    public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain ) throws IOException,
            ServletException
    {
        MDC_ELEMENT.setupMDCValues( request ) ;

        try
        {
            chain.doFilter( request, response ) ;
        }
        finally
        {
            MDC_ELEMENT.dropMDCValues() ;
        }
    }




    public enum MDC_ELEMENT
    {
        REMOTE_HOST( "remoteHost" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                return request.getRemoteHost() ;
            }
        }, //
        REQUEST_URI( "requestUri" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                return request.getRequestURI() ;
            }
        }, //
        QUERY_STRING( "queryString" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                return request.getQueryString() ;
            }
        }, //
        REQUEST_URL( "requestUrl" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                StringBuffer b = request.getRequestURL() ;
                return null == b ? null : b.toString() ;
            }
        }, //
        USER_AGENT( "userAgent" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                return request.getHeader( "User-Agent" ) ;
            }
        }, //
        X_FORWARDED_FOR( "xForwardedFor" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                return request.getHeader( "X-Forwarded-For" ) ;
            }
        }, //

        USER_PRINCIPAL( "user" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                Principal user = request.getUserPrincipal() ;
                return user.getName();

/*              if ( user == null )
                {
                    return "-" ;
                }
                else if ( !( user instanceof ZeusUser ) )
                {
                    return user.getName() ;
                }
                else
                {
                    return ( (ZeusUser) user ).getName() ;
                }*/
            }
        }, //

        SESSION_ID( "sessionId" )
        {
            @Override
            public String getValue( HttpServletRequest request )
            {
                HttpSession session = request.getSession() ;

                if ( null == session ) { return "" ; }

                return session.getId() ;
            }
        } ;

        private final String key ;

        private MDC_ELEMENT( String key )
        {
            this.key = key ;
        }

        public abstract String getValue( HttpServletRequest request ) ;


        public static void setupMDCValues( ServletRequest request )
        {
            for ( MDC_ELEMENT element : values() )
            {
                String value = null ;

                if ( request instanceof HttpServletRequest )
                {
                    value = element.getValue( (HttpServletRequest) request ) ;
                }

                MDC.put( element.key,  null == value ? "" : value ) ;
            }
        }

        public static void dropMDCValues()
        {
            for ( MDC_ELEMENT element : values() )
            {
                MDC.remove( element.key ) ;
            }
        }
    }
}
